﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Kokomo.Mirror.CliMetadata.Signatures
{
	class TypeRef : TypeSpec
	{
		public int typeToken;

		public override bool IsComplete
		{
			get { return (this.typeToken != 0); }
		}
		public override Type ResolveType(
			Module module,
			bool throwOnError,
			Type[] genericTypeArgs,
			Type[] genericMethodArgs
			)
		{
			Type t = module.ResolveType(this.typeToken, genericTypeArgs, genericMethodArgs);
			if (((object)t == null) && throwOnError)
				throw new TypeLoadException();

			return t;
		}

		public override string ToString()
		{
			return CodedIndex.FromToken(typeToken).ToString();
		}

		public override bool Equals(object obj)
		{
			TypeRef other = obj as TypeRef;
			if (other == null) return false;

			bool equals = (this.typeToken == other.typeToken);
			return equals;
		}

		public override bool Matches(
			Type type,
			Module module,
			Type[] genericTypeArguments,
			Type[] genericMethodArguments
			)
		{
			if ((object)type == null) throw new ArgumentNullException("type");

			bool matches =
				MemberEqualityComparer.Equal(type, this.ResolveType(
				module,
				false,
				genericTypeArguments,
				genericMethodArguments))
				;
			return matches;
		}
		public override bool Matches(
			Module ownerModule,
			TypeSpec other,
			Module otherModule
			)
		{
			if ((object)ownerModule == null) throw new ArgumentNullException("ownerModule");
			if (other == null) throw new ArgumentNullException("other");
			if ((object)otherModule == null) throw new ArgumentNullException("otherModule");

			TypeRef otherTypeRefSig = other as TypeRef;
			if (otherTypeRefSig == null) return false;

			ModuleMemberReference thisTypeRef = ModuleMemberReference.FromModuleToken(ownerModule, this.typeToken);
			ModuleMemberReference otherTypeRef = ModuleMemberReference.FromModuleToken(otherModule, otherTypeRefSig.typeToken);
			if (!thisTypeRef.IsCanonical)
				thisTypeRef = thisTypeRef.MakeCanonical();
			if (!otherTypeRef.IsCanonical)
				otherTypeRef = otherTypeRef.MakeCanonical();

			bool matches =
				thisTypeRef.Equals(otherTypeRef)
				;

			return matches;
		}
	}
}
